#include <avr/io.h>
#include <util/delay.h>

//-------------------------------------------------------------

//  6   5   4   3  2  1   0
// DB3 DB2 DB1 DB0 E R/W RS
#define LCD_DDR DDRD
#define LCD_PORT PORTD

#define LCD_RS 0
#define LCD_RW 1
#define LCD_E  2

#define LCD_DB4  4
#define LCD_DB5  5
#define LCD_DB6  6
#define LCD_DB7  7

void LCD_Send( const unsigned char c )
{
	LCD_PORT |= ( ( c >> 4 ) << LCD_DB4 );
	LCD_PORT |= ( 1 << LCD_E );
	LCD_PORT &= ~( 1 << LCD_E );

	LCD_PORT &= ~( ( 1 << LCD_DB4 ) | ( 1 << LCD_DB5 ) | ( 1 << LCD_DB6 ) | ( 1 << LCD_DB7 ) );

	LCD_PORT |= ( ( c & 0xf )<< LCD_DB4 );
	LCD_PORT |= ( 1 << LCD_E );
	LCD_PORT &= ~( 1 << LCD_E );
	_delay_ms(1);
}

void LCD_Data( const unsigned char c )
{
    LCD_DDR = 0xff;
    LCD_PORT =  ( 1 << LCD_RS );
    LCD_Send( c );
}

void LCD_Cmd( const unsigned char c )
{
    LCD_DDR = 0xff;
    LCD_PORT = 0;
    LCD_Send( c );
}

void LCD_PrintChar( char c )
{
	LCD_Cmd( (unsigned char)c );
}

void LCD_Print( const char *str )
{
	while( *str != 0 )
	{
		LCD_Data( (unsigned char)*str );
		str++;
	}
		
}
void LCD_Init()
{
   LCD_PORT = 0;
   LCD_DDR = 0xff;

   _delay_ms(15);

   LCD_PORT |= ( 1 <<LCD_DB4 ) | ( 1 << LCD_DB5 );

   LCD_PORT |= ( 1 << LCD_E );
   LCD_PORT &= ~( 1 << LCD_E );

   _delay_ms(5);

   LCD_PORT |= ( 1 <<LCD_DB4 ) | ( 1 << LCD_DB5 );

   LCD_PORT |= ( 1 << LCD_E );
   LCD_PORT &= ~( 1 << LCD_E );

   _delay_ms(1);

   LCD_Cmd( 0x32 );

   LCD_Cmd( 0x2C );

   LCD_Cmd( 0x0E );

   LCD_Cmd( 0x01 );

   LCD_Cmd( 0x06 );
}

void LCD_Demo()
{
   LCD_Print( "Raul" );

   LCD_Cmd( ( 1 << LCD_DB7 ) | 8 );

   LCD_Print( "Aguaviva" );

   LCD_Cmd( ( 1 << LCD_DB6 ) | 0 );
   LCD_Data( 0b00001110 );
   LCD_Data( 0b00011111 );
   LCD_Data( 0b00011111 );
   LCD_Data( 0b00011111 );
   LCD_Data( 0b00001110 );
   LCD_Data( 0b00000000 );
   LCD_Data( 0b00000000 );
   LCD_Data( 0b00000000 );

   LCD_Cmd( ( 1 << LCD_DB7 ) | 8 );
   LCD_Data( 0 );
}
